4a51b5c849ceec88ef7103940df291a2b8cdf652,src/org/exist/xquery/GeneralComparison.java,GeneralComparison,quickNodeSetCompare,#Sequence#,453
Before Change
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION CHOICE", "quickNodeSetCompare");
// if the context sequence hasn't changed we can return a cached result
if(cached != null && cached.isValid(contextSequence)) {
LOG.debug("Using cached results");
if(context.getProfiler().isEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Returned cached result");
return(cached.getResult());
}
//get the NodeSet on the left
NodeSet nodes = (NodeSet) getLeft().eval(contextSequence);
if(!(nodes instanceof VirtualNodeSet) && nodes.isEmpty()) //nothing on the left, so nothing to do
return(Sequence.EMPTY_SEQUENCE);
//get the Sequence on the right
Sequence rightSeq = getRight().eval(contextSequence);
if(rightSeq.isEmpty()) //nothing on the right, so nothing to do
return(Sequence.EMPTY_SEQUENCE);
//Holds the result
NodeSet result = null;
//get the type of a possible index
int indexType = nodes.getIndexType();
//See if we have a range index defined on the nodes in this sequence
//TODO : use isSubType ??? -pb
//rememeber that Type.ITEM means... no index ;-)
if(indexType != Type.ITEM) {
if (LOG.isTraceEnabled())
LOG.trace("found an index of type: " + Type.getTypeName(indexType));
//Get the documents from the node set
DocumentSet docs = nodes.getDocumentSet();
//Iterate through the right hand sequence
for (SequenceIterator itRightSeq = rightSeq.iterate(); itRightSeq.hasNext();) {
//Get the index key
Item key = itRightSeq.nextItem().atomize();
//if key has truncation, convert it to string
if(truncation != Constants.TRUNC_NONE) {
//TODO : log this conversion ? -pb
//truncation is only possible on strings
key = key.convertTo(Type.STRING);
}
//else if key is not the same type as the index
//TODO : use isSubType ??? -pb
else if (key.getType() != indexType) {
//try and convert the key to the index type
try {
key = key.convertTo(indexType);
} catch(XPathException xpe) {
//TODO : rethrow the exception ? -pb
//Could not convert the key to a suitable type for the index, fallback to nodeSetCompare()
if(context.getProfiler().isEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (" + xpe.getMessage() + ")");
if (LOG.isTraceEnabled())
LOG.trace("Cannot convert key: " + Type.getTypeName(key.getType()) + " to required index type: " + Type.getTypeName(indexType));
return nodeSetCompare(nodes, contextSequence);
}
}
// If key implements org.exist.storage.Indexable, we can use the index
if (key instanceof Indexable) {
if (LOG.isTraceEnabled())
LOG.trace("Checking if range index can be used for key: " + key.getStringValue());
if (Type.subTypeOf(key.getType(), indexType)) {
if(truncation == Constants.TRUNC_NONE) {
if (LOG.isTraceEnabled())
LOG.trace("Using range index for key: " + key.getStringValue());
//key without truncation, find key
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() +
"' to find key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
if (!checkForQNameIndex(contextSequence)) {
LOG.trace("Cannot use QName index");
contextQName = null;
}
NodeSet ns = context.getBroker().getValueIndex().find(relation, docs, nodes, NodeSet.ANCESTOR, contextQName, (Indexable)key);
hasUsedIndex = true;
if (result == null)
result = ns;
else
result = result.union(ns);
} else {
//key with truncation, match key
if (LOG.isTraceEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() +
"' to match key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
if (LOG.isTraceEnabled())
LOG.trace("Using range index for key: " + key.getStringValue());
try {
NodeSet ns = context.getBroker().getValueIndex().match(docs, nodes, NodeSet.ANCESTOR,
getRegexp(key.getStringValue()).toString(), null, DBBroker.MATCH_REGEXP);
hasUsedIndex = true;
if (result == null)
result = ns;
else
result = result.union(ns);
} catch (EXistException e) {
throw new XPathException(getASTNode(), e.getMessage(), e);
}
}
} else {
//the datatype of our key does not
//implement org.exist.storage.Indexable or is not of the correct type
if(context.getProfiler().isEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is of type: " +
Type.getTypeName(key.getType()) + ") whereas index is of type '" + Type.getTypeName(indexType) + "'");
if (LOG.isTraceEnabled())
LOG.trace("Cannot use range index: key is of type: " + Type.getTypeName(key.getType()) + ") whereas index is of type '" +
Type.getTypeName(indexType));
return(nodeSetCompare(nodes, contextSequence));
}
} else {
//the datatype of our key does not implement org.exist.storage.Indexable
After Change
if(rightSeq.isEmpty()) {
//Well, we might discuss this one ;-)
hasUsedIndex= true;
return Sequence.EMPTY_SEQUENCE;
}
//get the type of a possible index
int indexType = nodes.getIndexType();
//See if we have a range index defined on the nodes in this sequence
//TODO : use isSubType ??? -pb
//rememeber that Type.ITEM means... no index ;-)
if(indexType != Type.ITEM) {
if (LOG.isTraceEnabled())
LOG.trace("found an index of type: " + Type.getTypeName(indexType));
//Get the documents from the node set
DocumentSet docs = nodes.getDocumentSet();
//Holds the result
NodeSet result = null;
//Iterate through the right hand sequence
for (SequenceIterator itRightSeq = rightSeq.iterate(); itRightSeq.hasNext();) {
//Get the index key
Item key = itRightSeq.nextItem().atomize();
//if key has truncation, convert it to string
if(truncation != Constants.TRUNC_NONE) {
//TODO : log this conversion ? -pb
//truncation is only possible on strings
key = key.convertTo(Type.STRING);
}
//else if key is not the same type as the index
//TODO : use isSubType ??? -pb
else if (key.getType() != indexType) {
//try and convert the key to the index type
try {
key = key.convertTo(indexType);
} catch(XPathException xpe) {
//TODO : rethrow the exception ? -pb
//Could not convert the key to a suitable type for the index, fallback to nodeSetCompare()
if(context.getProfiler().isEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (" + xpe.getMessage() + ")");
if (LOG.isTraceEnabled())
LOG.trace("Cannot convert key: " + Type.getTypeName(key.getType()) + " to required index type: " + Type.getTypeName(indexType));
return nodeSetCompare(nodes, contextSequence);
}
}
// If key implements org.exist.storage.Indexable, we can use the index
if (key instanceof Indexable) {
if (LOG.isTraceEnabled())
LOG.trace("Checking if range index can be used for key: " + key.getStringValue());
if (Type.subTypeOf(key.getType(), indexType)) {
if(truncation == Constants.TRUNC_NONE) {
if (LOG.isTraceEnabled())
LOG.trace("Using range index for key: " + key.getStringValue());
//key without truncation, find key
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() +
"' to find key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
if (!checkForQNameIndex(contextSequence)) {
LOG.trace("Cannot use QName index");
contextQName = null;
}
NodeSet ns = context.getBroker().getValueIndex().find(relation, docs, nodes, NodeSet.ANCESTOR, contextQName, (Indexable)key);
hasUsedIndex = true;
if (result == null)
result = ns;
else
result = result.union(ns);
} else {
//key with truncation, match key
if (LOG.isTraceEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATIONS, "OPTIMIZATION", "Using value index '" + context.getBroker().getValueIndex().toString() +
"' to match key '" + Type.getTypeName(key.getType()) + "(" + key.getStringValue() + ")'");
if (LOG.isTraceEnabled())
LOG.trace("Using range index for key: " + key.getStringValue());
try {
NodeSet ns = context.getBroker().getValueIndex().match(docs, nodes, NodeSet.ANCESTOR,
getRegexp(key.getStringValue()).toString(), null, DBBroker.MATCH_REGEXP);
hasUsedIndex = true;
if (result == null)
result = ns;
else
result = result.union(ns);
} catch (EXistException e) {
throw new XPathException(getASTNode(), e.getMessage(), e);
}
}
} else {
//the datatype of our key does not
//implement org.exist.storage.Indexable or is not of the correct type
if(context.getProfiler().isEnabled())
context.getProfiler().message(this, Profiler.OPTIMIZATION_FLAGS, "OPTIMIZATION FALLBACK", "Falling back to nodeSetCompare (key is of type: " +
Type.getTypeName(key.getType()) + ") whereas index is of type '" + Type.getTypeName(indexType) + "'");
if (LOG.isTraceEnabled())
LOG.trace("Cannot use range index: key is of type: " + Type.getTypeName(key.getType()) + ") whereas index is of type '" +
Type.getTypeName(indexType));
return nodeSetCompare(nodes, contextSequence);
}
} else {
//our key does not implement org.exist.storage.Indexable